#include<bits/stdc++.h>
using namespace std;
#define ls p<<1
#define rs p<<1|1
typedef long long ll;
const int N=1e6+5;
ll d[N],v[N],a[N],p[N];
pair<ll,ll> pre[N];
ll nxt[N];
ll cnt1,cnt2;
ll n,m,L,V;
ll l[N],r[N];
ll cnt;
ll w[N];
struct SegT{
    struct node{
        int l,r;
        int maxn;
        int lazy;
        int id;
    }sgt[N<<2];
    void apply(int p,int d){
        sgt[p].maxn+=d;
        sgt[p].lazy+=d;
    }
    void pushup(int p){
        sgt[p].maxn=max(sgt[ls].maxn,sgt[rs].maxn);
        if(sgt[ls].maxn>sgt[rs].maxn)
            sgt[p].id=sgt[ls].id;
        else
            sgt[p].id=sgt[rs].id;
    }
    void pushdown(int p){
        if(sgt[p].lazy){
            apply(ls,sgt[p].lazy);
            apply(rs,sgt[p].lazy);
            sgt[p].lazy=0;
        }
    }
    void build(int p,int l,int r){
        sgt[p].l=l,sgt[p].r=r;
        if(l==r){
            sgt[p].maxn=w[l];
            sgt[p].id=l;
            return;
        }
        int mid=l+r>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(p);
    }
    void modify(int p,int l,int r,int d){
        if(l<=sgt[p].l&&sgt[p].r<=r){
            apply(p,d);
            return;
        }
        pushdown(p);
        int mid=sgt[p].l+sgt[p].r>>1;
        if(l<=mid)  modify(ls,l,r,d);
        if(r>mid) modify(rs,l,r,d);
        pushup(p);
    }
    node query(int p,int l,int r){
        if(l<=sgt[p].l&&sgt[p].r<=r){
            return sgt[p];
        }
        pushdown(p);
        int mid=sgt[p].l+sgt[p].r>>1;
        node ans={0,0,0,0,0};
        node man;
        if(l<=mid){
            man=query(ls,l,r);
            if(man.maxn>=ans.maxn){
                ans=man;
            }
        }
        if(r>mid){
            man=query(rs,l,r);
            if(man.maxn>ans.maxn){
                ans=man;
            }
        }
        return ans;
    }
}seg1,seg2;
void calc(int x){
    long long x1=0;
    if(a[x]>0){
        x1=(1ll*V*V-1ll*v[x]*v[x])/2/a[x];
        if(x1+d[x]<=L)
            nxt[++cnt2]=x1+d[x];
    }   
    if(a[x]==0&&v[x]>V){
        nxt[++cnt2]=d[x];
    }
    if(a[x]<0&&v[x]>V){
        x1=(1ll*V*V-1ll*v[x]*v[x])/2/a[x];
        seg1.modify(1,d[x],min(d[x]+x1,L),1);
        pre[++cnt1]=make_pair(d[x],min(d[x]+x1,L));        
    }
}
int main(){
    freopen("detect.in","r",stdin);
    freopen("detect.out","w",stdout);
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        cin>>n>>m>>L>>V;
        for(int i=1;i<=n;i++){
            nxt[i]=d[i]=a[i]=v[i]=0;
            cnt=cnt2=0;
        }
        seg1.build(1,1,L);
        for(int i=1;i<=n;i++){
            cin>>d[i]>>v[i]>>a[i];
            calc(i);
        }
        for(int i=1;i<=m;i++)
            cin>>p[i];
        sort(p+1,p+m+1);
        sort(pre+1,pre+cnt1+1);
        sort(nxt+1,nxt+cnt2+1);
        int pos=0;
        int ans1=0;
        int ans2=m;
        if(cnt2){
            pos=upper_bound(nxt+1,nxt+cnt2+1,p[m])-nxt-1;
            ans2--;
            ans1+=pos;
        }
        for(int i=1;i<=m;i++)
            w[i]=seg1.query(1,p[i],p[i]).maxn;
        seg2.build(1,1,m);
        for(int i=1;i<=cnt1;i++)
            l[i]=pre[i].first,r[i]=pre[i].second;
        int pos1=0,pos2=1,pos3=0,last,maxid;
        int l1,r1;
        while(pos2!=cnt1+1){
            last=pos2;
            pos3=upper_bound(p+1,p+m+1,r[last])-p-1;
            pos1=lower_bound(p+1,p+m+1,l[last])-p;
            if(pos1<=pos3){
                maxid=seg2.query(1,pos1,pos3).id;
                pos2=upper_bound(l+1,l+cnt1+1,p[maxid])-l;
                ans1+=seg2.query(1,pos1,pos3).maxn;
                ans2--;
                for(int i=last;i<pos2;i++){
                    int x=lower_bound(p+1,p+m+1,l[i])-p;
                    int y=upper_bound(p+1,p+m+1,r[i])-p-1;
                    seg2.modify(1,x,y,-1);
                }
            }
            else    
                pos2++;
        }
        if(p[maxid]>=nxt[pos]&&cnt2)
            ans2++;
        cout<<ans1<<" "<<ans2<<endl;
    }
    return 0;
}